package com.xyy.ec.qualification.service;

import com.alibaba.fastjson.JSON;
import com.xyy.ec.qualification.enums.TaskEnum;
import com.xyy.ec.qualification.exception.ServiceException;
import com.xyy.ec.qualification.pojo.PopRestDto;
import com.xyy.ec.qualification.pojo.SellerDataConfig;
import com.xyy.ec.qualification.task.TaskHandler;
import com.xyy.ec.qualification.utils.http.RedirectUtil;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;

import static com.xyy.ec.qualification.utils.MergedUrl.mergeUrl;

/**
 * 本地url方式
 * 注意url链接中如果有中文，则需要进行编码
 * url链接必须是 Http开头
 * @author leyan
 */
@Slf4j
@Service("localHttp")
public class LocalHttpUrlDataSyncServiceHandel extends DataSyncServiceHandel implements TaskHandler {

    @Override
    public void handleDrugReport(TaskEnum taskEnum) {
        syncErpDataToPop(taskEnum);
    }

    @Override
    public void handleFirstBattalionQualification(TaskEnum taskEnum) {
        syncErpDataToPop(taskEnum);
    }

    /**
     * 流转化为字节数组
     * @param inStream
     * @return
     * @throws Exception
     */
    public static byte[] readInputStream(InputStream inStream) throws Exception {

        try (ByteArrayOutputStream outStream = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[4096];
            int len;
            while ((len = inStream.read(buffer)) != -1) {
                outStream.write(buffer, 0, len);
            }
            return outStream.toByteArray();

        } finally { // 关闭输出流、输入流
            if (inStream != null) {
                inStream.close();
            }
        }
    }

    /**
     * 提取了获取文件后缀的逻辑到一个单独的方法getSuffix中，使代码更清晰
     * @param localUrl
     * @return
     */
    private static String getSuffix(String localUrl) {

        if (localUrl.endsWith(".jpg") || localUrl.endsWith(".png") || localUrl.endsWith(".jpeg")||localUrl.endsWith(".JPG") || localUrl.endsWith(".PNG") || localUrl.endsWith(".JPEG")) {
            return ".jpg";
        } else if (localUrl.endsWith(".pdf") || localUrl.endsWith(".PDF")) {
            return ".pdf";
        }
        return "";
    }

    /**
     * 对 URL 中的中文进行编码
     * @param url 原始 URL
     * @return 编码后的 URL
     * @throws Exception 编码过程中可能抛出的异常
     */
    private static String encodeUrlChinese(String url) throws Exception {
        String[] parts = url.split("/");
        for (int i = 0; i < parts.length; i++) {
            if (isChinese(parts[i])) {
                parts[i] = URLEncoder.encode(parts[i], "UTF-8");
            }
        }
        return String.join("/", parts);
    }

    /**
     * 判断字符串是否包含中文字符
     * @param str 待判断的字符串
     * @return 是否包含中文字符
     */
    private static boolean isChinese(String str) {
        return str.chars().anyMatch(ch -> Character.UnicodeScript.of(ch) == Character.UnicodeScript.HAN);
    }

    @Override
    public List<Map<String, Object>> fileConvert2Url(TaskEnum taskEnum, List<Map<String, Object>> serverResultList) {
        List<Map<String, Object>> newServerResultList = new ArrayList<>();
        if (CollectionUtils.isEmpty(serverResultList)) {
            return newServerResultList;
        }
        //请求头必须设置，否则报错
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json;charset=UTF-8");

        Map<String, String> params = new HashMap<>();
        params.put("appKey", SellerDataConfig.appKey);

        log.info("{}数据转化开始，待转化数据数量={}", taskEnum.getTaskName(),serverResultList.size());

        for (Map<String, Object> map : serverResultList) {
            try {
                Object o = map.get(taskEnum.getValueField());
                if (Objects.isNull(o) || !(o instanceof String)) {
                    log.error("{}地址格式异常，data={}", taskEnum.getTaskName(), JSON.toJSONString(o));
                    continue;
                }

                String localUrl = (String) o;

                if (localUrl.contains(",")) {
                    log.info("数据格式异常，data={}", localUrl);
                    continue;
                }

                //获取文件后缀
                String suffix = getSuffix(localUrl);
                if (suffix.isEmpty()) {
                    log.info("文件格式不支持，data={}", localUrl);
                    continue;
                }

                //对 URL 中的中文进行编码
                String  convertUrl = encodeUrlChinese(localUrl);


                URL url1 = new URL(convertUrl);
                HttpURLConnection conn = (HttpURLConnection) url1.openConnection();

                //超时响应时间为5秒
                conn.setConnectTimeout(5 * 1000);

                try(InputStream inStream = conn.getInputStream()) {
                    //处理输入流
                    byte[] data = readInputStream(inStream);

                    log.info("当前 {} 任务数据转化中,erpCode={},文件类型={}", taskEnum.getTaskName(),map.get(taskEnum.getQueryField()), suffix);

                    String url = RedirectUtil.doPostByFrom(getUploadUrl(), headers, params, UUID.randomUUID().toString()+suffix, data);

                    PopRestDto restDto = JSON.parseObject(url, PopRestDto.class);

                    if(Objects.isNull(restDto) || ! restDto.getStatus() || StringUtils.isBlank(restDto.getData())){
                        throw new ServiceException("文件上报异常");
                    }
                    Map<String, Object> newMap = new HashMap<>(map);
                    newMap.put(taskEnum.getValueField(), restDto.getData());
                    newServerResultList.add(newMap);
                }catch (Exception e) {
                    log.error("{}文件读取异常，data={}", taskEnum.getTaskName(), JSON.toJSONString(map), e);
                }
            } catch (Exception e) {
                log.info("{}数据转化异常，data={}", taskEnum.getTaskName(), JSON.toJSONString(map));
            }
        }
        return mergeUrl(newServerResultList,taskEnum.getTaskId());
    }
}
